from enum import Enum, auto


# https://blog.csdn.net/sinat_41104353/article/details/79314691
# <modifier-type-detail>
# type部分的内容是必须的，它通常用于描述普通的事件类型，例如鼠标点击或键盘按键点击
# modifier部分的内容是可选的，它通常用于描述组合键，例如Ctrl + c（<Control-Key-C>），Shift + 鼠标左键点击（<Shift-Button-1>）
# detail部分的内容是可选的，它通常用于描述具体的按键，例如Button-1表示的是鼠标左键
class EventModifier(Enum):
    Alt = auto()
    """当按下Alt按键的时候"""
    Any = auto()
    """表示任何类型的按键被按下的时候"""
    Control = auto()
    """当按下Ctrl按键的时候"""
    Double = auto()
    """当后续两个事件被连续触发的时候"""
    Lock = auto()
    """当打开大写字母锁定键（CapsLock）的时候"""
    Shift = auto()
    """当按下Shift按键的时候"""
    Triple = auto()
    """跟Double类似，当后续三个事件被连续触发的时候"""


class EventType(Enum):
    Active = auto()
    """当组件的状态从“未激活”变为“激活”的时候触发该事件"""
    Button = auto()
    """当用户点击鼠标按键的时候触发该事件
    detail部分指定是具体用哪个键： <Button-1>鼠标左键， <Button-2>鼠标中键（滚轮点击），<Button-3>鼠标右键，<Button-4>滚轮上滚（Linux），<Button-5>滚轮下滚（Linux）"""
    ButtonRelease = auto()
    """当用户释放鼠标按键的时候触发该事件
    在大多数情况下，比Button要更好使用，因为如果当用户不小心按下鼠标键，用户可以将鼠标移出组件再释放鼠标，从而避免不小心触发事件"""
    Configure = auto()
    """当组件的尺寸改变的时候触发该事件（窗口管理器触发的重绘事件，当你调整组件的尺寸或者移动应用程序，组件会和窗口一样被重绘）"""
    Deactivate = auto()
    """当组件的状态从“激活”变为“未激活”的时候触发该事件"""
    Destroy = auto()
    """当组件被销毁时触发该事件"""
    Enter = auto()
    """当鼠标指针进入组件的时候触发该事件
    注意：不是用户按下回车键（回车键是Return<Key-Return>）"""
    Expose = auto()
    """当窗口或组件的某部分不再被覆盖的时候触发该事件"""
    FocusIn = auto()
    """当组件获得焦点的时候触发该事件
    用户可以用Tab键将焦点转移到该组件上（需要该组件的takefocus选项为True）
    你也可以调用focus_set()
    方法使该组件获得焦点"""
    FocusOut = auto()
    """当组件失去焦点的时候触发该事件"""
    KeyPress = auto()
    """当用户按下键盘按键的时候触发该事件
    detail可以指定具体的按键，例如 <KeyPress-H>表示当大写字母H被按下的时候触发该事件
    KeyPress可以缩写为Key"""
    KeyRelease = auto()
    """当用户释放键盘按键的时候触发该事件"""
    Leave = auto()
    """当鼠标指针离开组件的时候触发该事件"""
    Map = auto()
    """当组件被映射的时候触发该事件
    意思是在应用程序中显示该组件的时候，例如调用get()方法"""
    Motion = auto()
    """当鼠标在组件内移动的时候触发该事件"""
    MouseWheel = auto()
    """当鼠标滚轮滚动的时候触发该事件
    目前该事件仅支持Windows和Mac系统"""
    Unmap = auto()
    """当组件被取消映射的时候触发该事件
    意思是在应用程序中不再显示该组件的时候，例如调用grid_remove()方法"""
    Visibility = auto()
    """当应用程序至少有一部分在屏幕中是可见的时候触发该事件"""


def event_intent(evt: EventType | str, modifier: EventModifier | str = '', detail='') -> str:
    """自定义事件时evt传入字符串"""
    ret = ''
    b = False
    if isinstance(modifier, EventModifier):
        modifier = modifier.name
    if len(modifier) != 0:
        ret += f'{modifier}-'
    if isinstance(evt, EventType):
        evt = evt.name
        b = True
    ret += evt
    if not isinstance(detail, str):
        detail = str(detail)
    if len(detail) != 0:
        ret += f'-{detail}'
    if b:
        return f'<{ret}>'
    else:
        return f'<<{ret}>>'
    pass


def event_generate(root, evt):
    root.event_generate(evt)


def event_bind(root, intent: str, target):
    root.bind(intent, target)

